www.gusucode.com > 有监督的 CNN 网络完成对MNIST 数字的识别 > 有监督的 CNN 网络完成对MNIST 数字的识别/CNN—卷积神经网络数字识别/@cnn/calcje.m

    function [cnet,je] = calcje(cnet,e)
%CALCJE Calculation of gradient via backpropagation 
%
%  Syntax
%  
%    [cnet,je] = calcje(cnet,e)
%    
%  Description
%   Input:
%    cnet - Convolutional neural network class object
%    e - error
%   Output:
%    cnet - convolutional neural network class object with computed
%    gradients
%    ge - gradient (or Jacobian times error)



%Last layer
k = cnet.numLayers;
%Calculate the performance function derrivative
cnet.FLayer{k}.dEdX{1} = feval(cnet.Perf, 'dy' , e, cnet.FLayer{k}.Y, cnet.FLayer{k}.X, cnet.Perf);
%Calculating the transfer function derrivative
cnet.FLayer{k}.dXdY{1} = feval(cnet.FLayer{k}.TransfFunc,'dn',cnet.FLayer{k}.Y,cnet.FLayer{k}.X); 
%Calculating dE/dY
cnet.FLayer{k}.dEdY{1} = cnet.FLayer{k}.dXdY{1}.*cnet.FLayer{cnet.numLayers}.dEdX{1};
%Check if the previous layer is convolutional or fully-connected
if(cnet.numFLayers~=1)
    outp = cnet.FLayer{cnet.numLayers-1}.X;
else
    outp = cnet.CLayer{cnet.numLayers-1}.XC;        
end
%Calculate gradients for weights and biases
cnet.FLayer{k}.dEdW{1} = kron(cnet.FLayer{k}.dEdY{1},outp)';
cnet.FLayer{k}.dEdB{1} = cnet.FLayer{k}.dEdY{1}';

%Reshape data into single-column vector
 je=cnet.FLayer{k}.dEdW{1};
 je=[je;cnet.FLayer{k}.dEdB{1}];

if (cnet.numFLayers>1) %If there are more than 1 fully-connected layers
    for k=cnet.numLayers-1:cnet.numLayers-cnet.numFLayers+1
        %Backpropagate error to outputs of this layer
        cnet.FLayer{k}.dEdX{1} = cnet.FLayer{k+1}.W*cnet.FLayer{k+1}.dEdY{1}';
        %補lculating the transfer function derrivative
        cnet.FLayer{k}.dXdY{1} = feval(cnet.FLayer{k}.TransfFunc,'dn',cnet.FLayer{k}.Y,cnet.FLayer{k}.X)'; %橡铊玮钿磬?趔黻鲨?嚓蜩忄鲨?
        %Backpropagate error to transfer function inputs
        cnet.FLayer{k}.dEdY{1} = cnet.FLayer{k}.dXdY{1}.*cnet.FLayer{k}.dEdX{1};
        %Check if the previous layer is convolutional or fully-connected
        if(cnet.numLayers-cnet.numFLayers+1==k)
             outp = cell2mat(cnet.CLayer{k-1}.XC);                
        else
             outp = cnet.FLayer{k-1}.X;
        end
        %Calculate gradients for weights and biases        
        cnet.FLayer{k}.dEdW{1} = kron(cnet.FLayer{k}.dEdY{1},outp); 
        cnet.FLayer{k}.dEdB{1} = cnet.FLayer{k}.dEdY{1};     

       %Reshape data into single-column vector
         je=[je;cnet.FLayer{k}.dEdW{1}];
         je=[je;cnet.FLayer{k}.dEdB{1}];    
    end
end

k = cnet.numLayers-cnet.numFLayers;
%Backpropagating the error
cnet.CLayer{k}.dEdX = num2cell(cnet.FLayer{k+1}.W*cnet.FLayer{k+1}.dEdY{1});
%dE/dY = dE/dX because of linear transfer function for C-layer
cnet.CLayer{k}.dEdY = cnet.CLayer{k}.dEdX;

for k=(cnet.numLayers-cnet.numFLayers):-1:2 %Exclude first layer from loop (it's dummy)
    if(rem(k,2)) %Parity check
    %Subsampling layer
    %Initialize dE/dX for accumilating the error
    dEdX = num2cell(zeros(cnet.SLayer{k}.numFMaps,1));
        for l=1:cnet.SLayer{k}.numFMaps %For all feature maps
            %補lculating the transfer function derrivative
            cnet.SLayer{k}.dXdY{l} = feval(cnet.SLayer{k}.TransfFunc,'dn',cnet.SLayer{k}.YS{l},cnet.SLayer{k}.XS{l}); 
            %Backpropagate error to transfer function inputs
            cnet.SLayer{k}.dEdY{l} = cnet.SLayer{k}.dXdY{l}.*cnet.SLayer{k}.dEdX{l};
            %Calculate the gradient for weights and biases
            cnet.SLayer{k}.dEdW{l} = sum(sum(cnet.SLayer{k}.dEdY{l}.*cnet.SLayer{k}.SS{l}));     
            cnet.SLayer{k}.dEdB{l}=sum(sum(cnet.SLayer{k}.dEdY{l}));    
            if(k>1) %Backpropagate the error if this is not the first layer
               dEdX{l} = back_subsample(cnet.SLayer{k}.dEdY{l}.*cnet.SLayer{k}.WS{l},cnet.SLayer{k}.SRate);
            end           
        end
       
    if(k>1) %Store the accumulated backpropagated error
        cnet.CLayer{k-1}.dEdX = reshape(dEdX,size(cnet.CLayer{k-1}.XC,1),size(cnet.CLayer{k-1}.XC,2),1);
    end
    %Reshape data into single-column vector
     je=[je;cell2mat(cnet.SLayer{k}.dEdW')];
     je=[je;cell2mat(cnet.SLayer{k}.dEdB')];
    
%---------------------------------------------------------------------------------------------    
    else
     %Convolutional layer
     %dE/dY = dE/dX because of linear transfer function for C-layer
     cnet.CLayer{k}.dEdY = cnet.CLayer{k}.dEdX;
     %Initialize temporary variables for accumilating the errors
     dEdX = num2cell(zeros(1,cnet.SLayer{k-1}.numFMaps));
     dEdW = num2cell(zeros(1,cnet.CLayer{k}.numKernels));
     dEdB = num2cell(zeros(1,cnet.CLayer{k}.numKernels));     
     for l=1:cnet.CLayer{k}.numKernels %碾?怦艴 ?屦 疋屦蜿?
            cnet.CLayer{k}.dXdY{l} = ones(size(cnet.CLayer{k}.XC{1})); %Transfer function is linear
            %For all feature maps of next layer wich have connections to
            %this layer
            for m=find(cnet.CLayer{k}.ConMap(l,:)) 
                %Backpropagate and accumulate the error
                dEdX{m} = dEdX{m}+...
                       back_conv2(cnet.SLayer{k-1}.XS{m}, cnet.CLayer{k}.dEdY{l},cnet.CLayer{k}.WC{l},'err');
                %Calculate and accumulate the shared weights gradient
                dEdW{l} = dEdW{l}+...
                       back_conv2(cnet.SLayer{k-1}.XS{m}, cnet.CLayer{k}.dEdY{l},cnet.CLayer{k}.WC{l},'gx'); 

                %Calculating the shared biases gradient
                dEdB{l}=dEdB{l} + sum(sum(cnet.CLayer{k}.dEdY{l})); 

            end
     end
     %Storing everithing
     cnet.SLayer{k-1}.dEdX = dEdX;
     cnet.CLayer{k}.dEdW = dEdW;
     cnet.CLayer{k}.dEdB = dEdB;
     %Reshape data into single-column vector
     je=[je;reshape(cell2mat(cnet.CLayer{k}.dEdW),[],1)];
     je=[je;cell2mat(cnet.CLayer{k}.dEdB)'];
        
    end
end



end